#region Imported Namespaces
using System;
using System.Collections;
using System.Data;
using System.Data.SqlClient;

using BO = PHSRAG.Insight21.BusinessObjects;
using DataAccess = PHSRAG.Utility.DataAccess;
using ICachePolicy = PHSRAG.Insight21.Policy.ICachePolicy;
using PHSRAG.Insight21.InsightUtilities;
using PHSRAG.Insight21.SearchContext;
using GenerateKey = PHSRAG.Insight21.BusinessObjects.ModuleKey;
#endregion

namespace PHSRAG.Insight21.Agreements
{
	public class RevenueBreakdowns : BO.BusinessObject
	{
		#region Constants
		private static string RevenueBreakdownsKey			= GenerateKey.MakeKey("RevenueBreakdowns_8021F7C5-E6F6-4fac-AB4C-4291DFDA1E3B",GenerateKey.Agreement);
		private const string RevenueBreakdownIDsTableName	= "GetRevenueBreakdown;1";
		private const string RevenueBreakdownTotalTableName = "RevenueBreakdownTotal";

		// Specifies where in the argument array the passed filtration and sorting information can be found.
		private enum ArgIndex
		{
            SessionIdIndex,
            DomainUserIdIndex,
            FundNumberIndex,
            FromDateIndex,
            ToDateIndex,
            TotalProvidedIndex,
            SortColumnIndex,
            SortOrderIndex,
            FullResultSetIndex,
            CumulativeIndex,
            AccountNumberIndex
        }
		#endregion

		#region Constructor
		/// <summary>
		/// Initialize the state of this object
		/// </summary>
		/// <param name="cachePolicy"></param>
		public RevenueBreakdowns() : base(null)
		{
			DataContainer = new DataSet();
		}
		#endregion

      #region Public Properties
      /// <summary>
      /// Get the key to be used in all caching operations for this instance of the object.
      /// </summary>
      public static string CacheKey { get { return RevenueBreakdownsKey; } }
      #endregion

      #region Public Methods
      /// <summary>
		/// Load the DataSet with RevenueBreakdown IDs and revenue total by executing the stored procedure
		/// "GetRevenueBreakdown".  Throws system exception if an error is encountered 
		/// during the load process.
		/// </summary>
		/// <remarks>
		/// There are two modes of operation for this method, depending on the value of args[ArgsIndex.FullResultSetIndex]:
		/// 0: Only the IDs are returned, the rest of the information is thrown out
		/// 1: The entire resultset is returned
		/// Within the first mode, if args[ArgsIndex.TotalProvidedIndex] is true no total information will be returned;
		/// if it is false the revenue total will also be stored alongside the ids in the DataContainer in a separate table.
		/// This method will also perform sorting on the requested data based on either default or specified sorting criteria
		/// in both modes.
		/// </remarks>
		/// <param name="connectionString">Sql Connection string info</param>
		/// <param name="args">Additional user or page defined parameters</param>
		public override void Load(string connectionString, params object[] args)
		{
            // Check the number of arguments
            if (args.Length != 11)
                throw new Exception("RevenueBreakdowns load requires 11 parameters");

			bool applySearchCriteria = (args[1] is SearchCriteria);
			
			try
			{
				DataContainer.Reset();

				DataSet revenueBreakdowns;
				string sessionId = (string)args[(int)ArgIndex.SessionIdIndex];
				string fromDate = (string)args[(int)ArgIndex.FromDateIndex];
				string toDate = (string)args[(int)ArgIndex.ToDateIndex];
				string sortColumn = (string)args[(int)ArgIndex.SortColumnIndex];
				string sortOrder = (string)args[(int)ArgIndex.SortOrderIndex];
				bool totalProvided = (bool)args[(int)ArgIndex.TotalProvidedIndex];
                string accountNumber = (string)args[(int)ArgIndex.AccountNumberIndex];
				// false: IDs only
				// true: Full resultset
				bool idsOnly = (args[(int)ArgIndex.FullResultSetIndex] == DBNull.Value ||
					(int)args[(int)ArgIndex.FullResultSetIndex] == 0);

				if(applySearchCriteria)
				{
					SearchCriteria searchCriteria = (SearchCriteria)args[1];
					System.Diagnostics.Trace.WriteLine(string.Format("{0}: SearchCriteria: {1}", DateTime.Now, searchCriteria.ToString()));

					object includeProgramProjects = searchCriteria[Constants.IncludeProgramProjectsKey];
					bool includeDirect = (includeProgramProjects == null) ? false : Convert.ToBoolean(includeProgramProjects);

                    string glPostAsOfDate = searchCriteria[Constants.GLPostAsOfDateKey];
                    if (glPostAsOfDate != null)
                        Convert.ToDateTime(glPostAsOfDate).ToShortDateString();

					revenueBreakdowns = DataAccess.GetDataSet(connectionString, "GetRevenueBreakdown",
						DataAccess.BuildSqlParameterArray(
						"@sessionId",					SqlDbType.VarChar,	sessionId,
						"@domainUserId",				SqlDbType.Int,		searchCriteria[Constants.DomainUserIDKey],
						"@includeProgramProjects",		SqlDbType.Bit,		includeDirect,
						"@fundNumber",					SqlDbType.VarChar,	searchCriteria[Constants.FundIDKey],
						"@folderNumber",				SqlDbType.VarChar,	searchCriteria[Constants.FolderNumberKey],
						"@bicsNumber",					SqlDbType.VarChar,	searchCriteria[Constants.BicsNumberKey],
						"@walkerNumber",				SqlDbType.VarChar,	searchCriteria[Constants.WalkerNumberKey],
						"@sponsorNumber",				SqlDbType.VarChar,	searchCriteria[Constants.SponsorNumberKey],
						"@sponsorName",					SqlDbType.VarChar,	searchCriteria[Constants.SponsorNameKey],
						"@sponsorTypeId",				SqlDbType.Int,		searchCriteria[Constants.SponsorTypeIDKey],
						"@agreementTypeId",				SqlDbType.Int,		searchCriteria[Constants.AgreementTypeIDKey],
						"@activityCode",				SqlDbType.VarChar,	searchCriteria[Constants.ActivityCodeKey],
						"@locationId",					SqlDbType.Int,		searchCriteria[Constants.LocationIDKey],
						"@fromDate",					SqlDbType.DateTime,	(fromDate == string.Empty) ? "01/01/1900" : fromDate,
						"@toDate",						SqlDbType.DateTime, (toDate== string.Empty) ? DateTime.Now.ToShortDateString() : toDate,
						"@projectStartDate",			SqlDbType.DateTime,	searchCriteria[Constants.ProjectStartDateKey],
						"@projectEndDate",				SqlDbType.DateTime,	searchCriteria[Constants.ProjectEndDateKey],
						"@piId",						SqlDbType.Int,		searchCriteria[Constants.PIIDKey],
						"@chiefCodeList",				SqlDbType.VarChar,	searchCriteria.COSIds,
						"@sponsorGroupTypeId",			SqlDbType.Int,		searchCriteria[Constants.ViewingOptionKey],
						"@budgetEndingDays",			SqlDbType.Int,		searchCriteria[Constants.DaysBudgetEndingKey],
						"@projectEndingDays",			SqlDbType.Int,		searchCriteria[Constants.DaysProjectEndingKey],
						"@fundCreatedDays",				SqlDbType.Int,		searchCriteria[Constants.DaysFundCreatedKey],
						"@lowBalance",					SqlDbType.Decimal,	searchCriteria[Constants.BalanceLessThanKey],
						"@highBalance",					SqlDbType.Decimal,	searchCriteria[Constants.BalanceGreaterThanKey],
						"@agreementStatusTypeList",		SqlDbType.VarChar,	searchCriteria[Constants.AgreementStatusIDKey],
						"@fundStatusTypeId",			SqlDbType.Int,		searchCriteria[Constants.FundStatusIDKey],
						"@categoryId",					SqlDbType.Int,		Convert.ToInt32(searchCriteria[Constants.CategoryIDKey]),
                        "@accountNumber",               SqlDbType.Int,      args[(int)ArgIndex.AccountNumberIndex],
						"@glPostAsOfDate",				SqlDbType.DateTime,	glPostAsOfDate,
						"@finJournalTransactionSrcId",	SqlDbType.Int,		DBNull.Value,
						"@isDetail",					SqlDbType.Bit, false ));
				}
				else
				{
					int domainUserId = (int)args[(int)ArgIndex.DomainUserIdIndex];
					// Fund number is allowed to be null, but needs to be formatted so the stored procedure works
					string fundNumber = (string)args[(int)ArgIndex.FundNumberIndex];
                    int cumulative = (int)args[(int)ArgIndex.CumulativeIndex];
                    if (fundNumber == null) fundNumber = "";

					revenueBreakdowns = DataAccess.GetDataSet(connectionString, "GetRevenueBreakdown",
						DataAccess.BuildSqlParameterArray(
						"@sessionId",					SqlDbType.VarChar,	sessionId,
						"@domainUserID",				SqlDbType.Int,		domainUserId,
						"@fundNumber",					SqlDbType.VarChar,	fundNumber,
						"@fromDate",					SqlDbType.DateTime,	(fromDate == string.Empty) ? "01/01/1900" : fromDate,
						"@toDate",						SqlDbType.DateTime, (toDate== string.Empty) ? DateTime.Now.ToShortDateString() : toDate,
						"@finJournalTransactionSrcId",	SqlDbType.Int,		DBNull.Value,
                        "@isDetail",                    SqlDbType.Bit, true,
                        "@cumulative", SqlDbType.Int, cumulative,
                        "@accountNumber", SqlDbType.Int, (accountNumber == string.Empty) ? null : args[(int)ArgIndex.AccountNumberIndex]));
                }
				
				// Sort the full resultset that was returned
				DataView dataView = new DataView(revenueBreakdowns.Tables[0]);
				string sort = "";
				switch (sortColumn)
				{
					case "FundNumber":
						sort = String.Format("FundNumber {0}, AccountNumber, DatePosted desc", sortOrder);
						break;

					case "ProjectTitle":
						sort = String.Format("ProjectTitle {0}, AccountNumber, DatePosted desc", sortOrder);
						break;

					case "SponsorName":
						sort = String.Format("SponsorName {0}, AccountNumber, DatePosted desc", sortOrder);
						break;

					case "PIName":
						sort = String.Format("PIName {0}, AccountNumber, DatePosted desc", sortOrder);
						break;

					case "AccountNumber":
						sort = String.Format("AccountNumber {0}, FundNumber, DatePosted desc", sortOrder);
						break;

					case "AccountName":
						sort = String.Format("AccountName {0}, AccountNumber, DatePosted desc", sortOrder);
						break;

					case "Amount":
						sort = String.Format("Amount {0}, AccountNumber, DatePosted desc", sortOrder);
						break;

					case "DatePosted":
						sort = String.Format("DatePosted {0}, FundNumber, AccountNumber", sortOrder);
						break;

					default:
						sort = String.Format("FundNumber {0}, AccountNumber, DatePosted desc", sortOrder);
						break;
				}
				dataView.Sort = sort;

				DataTable total = new DataTable(RevenueBreakdownTotalTableName);

				// Trim resultset to ID column only if the full resultset is not required and include total data only if needed
                if (!totalProvided)
                {
                    total.Columns.Add(new DataColumn("RevenueTotal",System.Type.GetType("System.Decimal"),"",MappingType.Hidden));

                    if (dataView.Count > 0)
                    {
                        DataRow dataRow = total.NewRow();
                        dataRow["RevenueTotal"]	= (decimal) dataView.Table.Compute("sum(Amount)","");
                        total.Rows.Add(dataRow);
                    }
                }

                if (idsOnly)
				{
					for (int i = dataView.Table.Columns.Count - 1; i > 0; --i)
					{
						if (dataView.Table.Columns[i].ColumnName != "TransactionID")
							dataView.Table.Columns.RemoveAt(i);
					}
				}

                /* Modifier - at098, 01/16/2008 4:30 PM
                 * The next 5 lines of code have been commented out for a more efficient approach*/

				// Create a data table from the data view output                
                DataTable dataTable = dataView.Table.Clone();
                dataTable.TableName = RevenueBreakdownIDsTableName;
                foreach (DataRowView dataRowView in dataView)
                    dataTable.ImportRow(dataRowView.Row);
                
                //DataTable dataTable = dataView.Table.Copy(); //efficient approach
                //dataTable.TableName = RevenueBreakdownIDsTableName;

				// Create the dataset with up to 2 tables (if applicable)
				DataSet ds = new DataSet();

				ds.Tables.Add(dataTable);
				if (!totalProvided) ds.Tables.Add(total);

				DataContainer = ds;
			}
			catch(Exception e)
			{
				DataContainer = null;
				throw(new Exception(String.Format("{0} This occurred while getting Revenue Breakdown",Utility.ExceptionReport.GetExceptionInfo(e, false)),e.InnerException));
			}
		}
		#endregion
	}
}

// --- EOF ---